import React from 'react'

import './index.less'
import Board from '../Board'

  class Game extends React.Component<any, any> {
    constructor(
      { specs, 
        FirstHandSign,
        BackHandSign,
        heightLightStyle,
        Position,
        Sort 
      } :
      {
        specs?: number,
        FirstHandSign?: number | string,
        BackHandSign?: number | string,
        heightLightStyle?: object | null,
        Position?: boolean,
        Sort?: boolean
      }
      ) {
      super(...arguments) ;
       
      this.state = {
        specs: specs ? specs : 3,
        history: [{
          squares: Array(specs ? specs*specs : 9).fill(null),
          controlIndex: 0 // 点击的控件标签,用于设置控件坐标
        }],
        xIsNext: true,
        step: 0, // 时间回溯步骤
        order: true, // 默认历史记录顺序排列
        allPossibilities: calculateWinnerPossibilities(specs ? specs : 3),
        FirstHandSign: FirstHandSign ? FirstHandSign : 'X',
        BackHandSign: BackHandSign ? BackHandSign : 'O',
        heightLightStyle: heightLightStyle ? heightLightStyle : {backgroundColor: 'lightblue'},
        Position: Position ? Position : true,
        Sort: Sort ? Sort : true
      }
    }

    handleClick(i:number) {
      let history = this.state.order ? this.state.history.slice(0, this.state.step + 1)
        : this.state.history.slice(this.state.history.length - this.state.step - 1, this.state.history.length); // 当前进度记录，顺序排列则截取开始到选择步骤，逆序排列截取步骤到数组尾
      let current = this.state.order ? history[history.length - 1] : history[0];
      let squares = current.squares.slice(); 
      if(squares[i] || calculateWinner(squares, this.state.allPossibilities)) { // 已决出胜者或控件已填则返回
        return;
      }
      squares[i] = this.state.xIsNext ? this.state.FirstHandSign : this.state.BackHandSign;
      this.setState({
        history: this.state.order ? 
        history.concat([{squares, controlIndex: i}]) :
        [{squares, controlIndex: i}].concat(history), // concat 方法不会改变原数组，顺序排列从原数组尾部添加新纪录，逆序排序将原纪录添加到新纪录尾部
        step: history.length,
        xIsNext: !this.state.xIsNext,
      });
    }
    
    jumpTo(step:number) {
      this.setState({
        step,
        xIsNext: (step % 2) === 0
      })
    }

    sort() {
      let history = this.state.history.slice();
      history.sort((pre, next) => {
        return (
        history.indexOf(next) - history.indexOf(pre)
        )
      });
      this.setState({
        order: !this.state.order,
        history
        }
      )
    }

    render() {
      const history = this.state.history;
      const current = this.state.order ? history[this.state.step] : history[history.length - this.state.step - 1]; // 根据排序顺序从步骤纪录中获取对应的控件控件数据表
      
      const winner = calculateWinner(current.squares, this.state.allPossibilities);
      const draw = current.squares.includes(null); // 如果不再含有null 则证明九宫格已全部填完
      const moves = history.map((step, move, array) => {
        let go = this.state.order ? move : history.length - move - 1; // history.length - move - 1 设置逆序排列的步骤对应其的history 纪录表中的数据
        let currnetPosition = this.state.Position ? (' (' + (parseInt(step.controlIndex / 3) + 1) + ',' + (step.controlIndex % 3 + 1) + ')') : '';
        const desc = this.state.order ? (move ? 'Go to move #' + move + currnetPosition : 'Go to game start') :
        (move !== (array.length -1) ? 'Go to move #' + (array.length - move - 1) + currnetPosition : 'Go to game start'); // 逆序下如果当前history 下标不是数组末尾，则为下棋纪录
        return (
          <li key={step.squares}>
            <button 
            style = {move === (this.state.order ? this.state.step : history.length - this.state.step - 1) ? {fontWeight: '900'} : {}}
            onClick = {() => this.jumpTo(go)}
            >{desc}</button>
          </li>
        )
      })
      let status;
      if(winner) {
        status = current.squares[winner[0]] + ' Win!';
      }else if(draw){
        status = 'Next Player: ' + (this.state.xIsNext ? this.state.FirstHandSign : this.state.BackHandSign);
      }else {
        status = 'It ends in a draw'
      }

      return (
        <div className="game">
          <div className="game-board">
            <Board
              cellContent = {current.squares}
              heightLight = {winner} 
              click = { i => this.handleClick(i) }/>
          </div>
          <div className="game-info">
            <div className="game-info-header">
              <div>{ status }</div>
              { this.state.Sort ? <button onClick = {() => this.sort()}>{this.state.order ? '降序' : '升序'}</button> : null }
            </div>
            <ol className="action-history-list">{ moves }</ol>
          </div>
        </div>
      );
    }
  }
  
  export default Game

  function calculateWinnerPossibilities(specs:number) {
    let count = specs -3;
    let start = 0;
    const lines = [
      [0, 1, 2],
      [specs, specs+1, specs+2],
      [2*specs, 2*specs+1, 2*specs+2],
      [0, specs, 2*specs],
      [1, specs+1, 2*specs+1],
      [2, specs+2, 2*specs+2],
      [0, specs+1, 2*specs+2],
      [2, specs+1, 2*specs],
    ];
    const AllPossibilities = [];
    for(let i = 0; i<= count; i++) {
      for(let j = 0; j<= count; j++) {
        let newLines:any = [];
        lines.forEach((item,index) => {
          newLines[index] = item.map(value => value+=i+j*specs)
        })
        AllPossibilities[start] = newLines;
        start ++;
      }
    }
    
    return AllPossibilities.length ? AllPossibilities : [lines];
  }

  function calculateWinner(squares:Array<any>, allPossibilities:Array<Array<number>>):number[] | null {
    for(let i of allPossibilities) {
      for(let item of i) {
        let [a, b, c]:any = item;
        if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
          return [a,b,c];
        }
      }
    }
    return null;
  }


  